package org.light.complexverb;

import java.util.ArrayList;
import java.util.List;

import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.Type;
import org.light.generator.NamedStatementListGenerator;
import org.light.oracle.generator.MybatisOracleSqlReflector;
import org.light.utils.MybatisSqlReflector;
import org.light.utils.PgsqlReflector;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class ListMyActive extends TwoDomainVerb{

	@Override
	public Method generateDaoImplMethod() throws Exception {
		Method method = new Method();
		method.setStandardName(StringUtil.capFirst(this.getVerbName()));
		method.setNoContainer(false);
		method.addSignature(new Signature(1, "&self",""));
		method.addSignature(new Signature(2, this.master.getDomainId().getSnakeFieldName(),this.master.getDomainId().getFieldType()));
		method.setReturnType(new Type("Result<Vec<"+this.slave.getCapFirstDomainNameWithSuffix()+">, sqlx::Error>"));
		method.addAdditionalImport("super::"+this.slave.getCapFirstDomainNameWithSuffix());	
		method.setTempTag(this.slave.getCapFirstDomainNameWithSuffix());
		
		List<Writeable> sList = new ArrayList<Writeable>();
		long serial = 1000L;
		sList.add(new Statement(serial+2000L,2,"sqlx::query_as("));
		if (StringUtil.isBlank(this.getDbType())||this.getDbType().equalsIgnoreCase("MariaDB")||this.getDbType().equalsIgnoreCase("MySQL")) {
			sList.add(new Statement(serial+3000L,3,"r#\""+MybatisSqlReflector.generateSelectActiveUsingMasterIdStatement(master,slave)+"\"#"));
		} else if (this.getDbType().equalsIgnoreCase("PostgreSQL")||this.getDbType().equalsIgnoreCase("pgsql")) {
			sList.add(new Statement(serial+3000L,3,"r#\""+PgsqlReflector.generateSelectActiveUsingMasterIdStatement(master,slave)+"\"#"));
		} else if (this.getDbType().equalsIgnoreCase("Oracle")) {
			sList.add(new Statement(serial+3000L,3,"r#\""+MybatisOracleSqlReflector.generateSelectActiveUsingMasterIdStatement(master,slave)+"\"#"));
		}
		sList.add(new Statement(serial+3500L,2,")"));
		sList.add(new Statement(serial+4000L,2,".bind("+this.master.getDomainId().getSnakeFieldName()+")"));
		sList.add(new Statement(serial+5000L,2,".fetch_all(&*self.pool)"));
		sList.add(new Statement(serial+6000L,2,".await"));
		method.setMethodStatementList(WriteableUtil.merge(sList));
		return method;
	}
	@Override
	public Method generateDaoMethodDefinition() throws Exception {
		Method method = new Method();
		method.setStandardName(StringUtil.capFirst(this.getVerbName()));
		method.setReturnType(new Type("[] "+this.slave.getDomainSuffix()+"."+this.slave.getType()));
		method.addSignature(new Signature(1, "db","*sql.DB"));
		method.addSignature(new Signature(2,this.master.getLowerFirstDomainName()+"Id",this.master.getDomainId().getClassType()));
		method.setThrowException(true);
		return method;
	}
	@Override
	public Method generateServiceMethodDefinition() throws Exception {
		Method method = new Method();
		method.setStandardName(StringUtil.capFirst(this.getVerbName()));
		method.setReturnType(new Type("[] "+this.slave.getDomainSuffix()+"."+this.slave.getType()));
		method.addSignature(new Signature(1,this.master.getLowerFirstDomainName()+"Id", this.master.getDomainId().getClassType()));
		method.setThrowException(true);
		return method;
	}
	@Override
	public Method generateServiceImplMethod() throws Exception {
		Method method = new Method();
		method.setStandardName(StringUtil.capFirst(this.getVerbName()));		
		method.addSignature(new Signature(1, this.master.getDomainId().getSnakeFieldName(),this.master.getDomainId().getFieldType()));
		method.setReturnType(new Type("Result<Vec<"+this.slave.getCapFirstDomainNameWithSuffix()+">, sqlx::Error>"));
		method.addAdditionalImport(this.slave.getProjectName()+"::"+this.slave.getDomainSuffix()+"::"+this.slave.getCapFirstDomainNameWithSuffix());
		
		List<Writeable> sList = new ArrayList<Writeable>();
		long serial = 1000L;
		sList.add(new Statement(serial+1000L,1,"let app_state = init_db();"));
		sList.add(new Statement(serial+2000L,1,"app_state.await.context."+StringUtil.getSnakeName(this.slave.getPlural())+"."+StringUtil.getSnakeName(this.getVerbName())+"("+this.master.getDomainId().getSnakeFieldName()+").await"));

		method.setMethodStatementList(WriteableUtil.merge(sList));
		return method;
	}
	@Override
	public Method generateControllerMethod() throws Exception {
		Method method = new Method();
		method.setStandardName(StringUtil.capFirst(this.getVerbName()));
		method.addSignature(new Signature(1,"Form("+this.master.getSnakeDomainName()+"_"+StringUtil.getSnakeName(this.slave.getAliasOrName())+"_mtm_request)","Form<"+this.master.getCapFirstDomainName()+StringUtil.capFirst(this.slave.getAliasOrName()+"MtmRequest>")));
		method.setReturnType(new Type("String"));
		method.addAdditionalImport(this.slave.getProjectName()+"::"+this.slave.getDomainSuffix()+"::"+this.slave.getCapFirstDomainNameWithSuffix());
		
		List<Writeable> sList = new ArrayList<Writeable>();
		long serial = 1000L;
		sList.add(new Statement(serial+1000L,1,"let "+this.master.getDomainId().getSnakeFieldName()+" = "+this.master.getSnakeDomainName()+"_"+StringUtil.getSnakeName(this.slave.getAliasOrName())+"_mtm_request."+this.master.getSnakeDomainName()+"_id.unwrap_or_default();"));
		sList.add(new Statement(serial+2000L,0,""));
		sList.add(new Statement(serial+3000L,1,"let "+StringUtil.getSnakeName(this.slave.getPlural())+" = service_"+StringUtil.getSnakeName(this.getVerbName())+"("+this.master.getDomainId().getSnakeFieldName()+").await;"));
		sList.add(new Statement(serial+4000L,1,"match "+StringUtil.getSnakeName(this.slave.getPlural())+" {"));
		sList.add(new Statement(serial+5000L,2,"Err(_) => {"));
		sList.add(new Statement(serial+6000L,3,"println!(\"Error!\");"));
		sList.add(new Statement(serial+7000L,3,"return \"Error!\".to_string();"));
		sList.add(new Statement(serial+8000L,2,"},"));
		sList.add(new Statement(serial+9000L,2,"Ok(mut "+StringUtil.getSnakeName(this.slave.getPlural())+") => {"));
		sList.add(new Statement(serial+10000L,3,"let json = serde_json::to_string_pretty(&"+StringUtil.getSnakeName(this.slave.getPlural())+").unwrap();"));
		sList.add(new Statement(serial+11000L,3,"println!(\"{}\", json);"));
		sList.add(new Statement(serial+12000L,0,""));
		sList.add(new Statement(serial+13000L,3,"let mut map = Map::new();"));
		sList.add(new Statement(serial+14000L,3,"map.insert(\"success\".to_string(), Value::from(true));"));
		sList.add(new Statement(serial+15000L,3,"map.insert("));
		sList.add(new Statement(serial+16000L,4,"\"rows\".to_string(),"));
		sList.add(new Statement(serial+17000L,4,"serde_json::from_str(&json).unwrap(),"));
		sList.add(new Statement(serial+18000L,3,");"));
		sList.add(new Statement(serial+19000L,2,""));
		sList.add(new Statement(serial+20000L,3,"let resultjson = serde_json::to_string_pretty(&map).unwrap();"));
		sList.add(new Statement(serial+21000L,3,"println!(\"{}\", resultjson);"));
		sList.add(new Statement(serial+22000L,3,"return resultjson;"));
		sList.add(new Statement(serial+23000L,2,"}"));
		sList.add(new Statement(serial+24000L,1,"}"));
		method.setMethodStatementList(WriteableUtil.merge(sList));
		return method;
	}

	public ListMyActive(Domain master,Domain slave){
		super();
		this.master = master;
		this.slave = slave;
		this.setVerbName("ListActive"+this.master.getCapFirstDomainName()+StringUtil.capFirst(this.slave.getAliasPlural())+"Using"+this.master.getCapFirstDomainName()+"Id");
		this.setLabel("列出所属");
		this.dbType = master.getDbType();
	}

}
